home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Font Handler / FontHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  16.3 KB  |  580 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        FontHandler.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.  
  6.      Version:    Technology:    Quickdraw GX 1.1.x
  7.       
  8.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #include <GXExceptions.h>
  12. #include <String.h>
  13. #include <Resources.h>
  14. #include <MacMemory.h>
  15. #include <Collections.h>
  16. #include "IOUtilities.h"
  17. #include "GXToPSBuildConfig.h"
  18. #include "GXPrintingUniverse.h"
  19. #include "PSProcSetIDs.h"
  20. #include "FontDatabase.h"
  21. #include "FontHandler.h"
  22. #include "FontHandlerPrivate.h"
  23. #include "FontHandlerVariations.h"
  24.  
  25. #ifdef resumeLabel
  26.     #undef resumeLabel
  27. #endif
  28. #define resumeLabel(exception)
  29.  
  30.  
  31.  
  32.  
  33. /****************************************
  34.  
  35.     Function FHBuildPrinterFontList
  36.     
  37.     Function builds the printer font database from
  38.     the document font database.
  39.  
  40.     hFHRec:            Handle to a font handler record.
  41.         
  42. *****************************************/
  43. OSErr    FHBuildPrinterFontList(TFontHandlerHdl hFHRec);
  44. OSErr    FHBuildPrinterFontList(TFontHandlerHdl hFHRec)
  45.     {
  46.         OSErr                                    status;
  47.         long                                    nFonts;                            // Number of document fonts.
  48.         long                                    idx;                                // loop counter.
  49.         long                                    varCounter;                    // variation counter.
  50.         gxFont                                theFont;                        // A particular document font.
  51.         fhFont                                snapshotID;                    // snapshot id.
  52.         TFontDbase                        docDbase;                        // the document font database.
  53.         unsigned long                    *glyphBits;                    // glyph usage bits for a document font.
  54.         TfdbInfoFlags                    fontFlags;                    // Font database flags for this font.
  55.         long                                    nGlyphs;                        // Number of glyphs in the font.
  56.         long                                    axisCount;                    // Number of variation axes supported by the font.
  57.         long                                    variationCount;            // Number of variations used in this font.
  58.         TFHStreamRequirements    streamRequirements;    // Streaming requirements for this font.
  59.         
  60.         docDbase = (*hFHRec)->docDbase;
  61.         
  62.         nrequire(status = FontDbaseCountFonts(docDbase, &nFonts), failed_FontCount);
  63.         nrequire(status = FontDbaseLock(docDbase), failed_Lock);
  64.  
  65.         /*** For each document font, build the printer font items in the printer font database. **/
  66.                 
  67.         for (idx = 1; idx <= nFonts; ++idx) {
  68.  
  69.             status = FontDbaseGetIndexedFont(docDbase, idx, &theFont);
  70.             nrequire(status, failed_GetIndFont);
  71.             
  72.             status = FontDbaseGetFontInfo(docDbase, theFont, &nGlyphs, &axisCount, &variationCount, &fontFlags);
  73.             nrequire(status, failed_info);
  74.             
  75.             status = FHGetStreamRequirements(theFont, (*hFHRec)->psDevice, (*hFHRec)->legalStreamTypes,
  76.                                                                                 (*hFHRec)->productDescription, &streamRequirements);
  77.             nrequire(status, failed_testSnapshots);
  78.             
  79.             if (streamRequirements == fhNeedsSnapShots) {
  80.             
  81.                 /** Make printer fonts for all of the variations **/
  82.             
  83.                 for (varCounter = 1; varCounter <= variationCount; ++varCounter) {
  84.                 
  85.                     status = FontDbaseGetGlyphBits(docDbase, theFont, varCounter, &glyphBits, nil);
  86.                     nrequire(status, failed_bits);
  87.                     
  88.                     status = FHAddFontSnapShot(hFHRec, theFont, varCounter, &snapshotID);
  89.                     nrequire(status, failed_snapshot);
  90.                             
  91.                     status = FHAddPrinterFonts(hFHRec, snapshotID, glyphBits, nGlyphs, fontFlags);
  92.                     nrequire(status, failed_AddPrFont);
  93.                 
  94.                 }//end for
  95.                 
  96.             } else {
  97.             
  98.                 /*****
  99.                     Either the font doesn't need snapsonts or it can't be streamed,
  100.                     in any event, we only need one Snapshot for all variations (main bits)
  101.                 *****/
  102.             
  103.                 status = FontDbaseGetGlyphBits(docDbase, theFont, eMainBits, &glyphBits, nil);
  104.                 nrequire(status, failed_bits);
  105.  
  106.                 status = FHAddFontSnapShot(hFHRec, theFont, eMainBits, &snapshotID);
  107.                 nrequire(status, failed_snapshot);
  108.                         
  109.                 status = FHAddPrinterFonts(hFHRec, snapshotID, glyphBits, nGlyphs, fontFlags);
  110.                 nrequire(status, failed_AddPrFont);
  111.             
  112.             }//end if
  113.  
  114.         }//end for
  115.                 
  116.         status = FontDbaseUnlock(docDbase);
  117.         ncheck(status);
  118.                 
  119. failed_AddPrFont:
  120. failed_snapshot:
  121. failed_bits:
  122. failed_testSnapshots:
  123. failed_info:
  124. failed_GetIndFont:
  125. failed_Lock:
  126. failed_FontCount:
  127.  
  128.         return(status);
  129.         
  130.     }//FHBuildPrinterFontList
  131.     
  132.  
  133. //<FF>
  134. /****************************************
  135.  
  136.     Function: FHMakeProductDescripton
  137.     
  138.     Function combines the three components
  139.     of the product description into the single
  140.     C string necessary to pass in to the GXFlattenFont
  141.     routine.
  142.     
  143.     productDescription:                    (returned)  Pointer to description allocated here.
  144.     version:                                        Pascal string for version
  145.     revision:                                        Pascal string for revision
  146.     product                                            Pascal string for product-name.
  147.     
  148. *****************************************/
  149. OSErr FHMakeProductDescription(unsigned char* *productDescription, unsigned char *version, unsigned char* revision, unsigned char* product);
  150. OSErr FHMakeProductDescription(unsigned char* *productDescription, unsigned char *version, unsigned char* revision, unsigned char* product)
  151.     {
  152.         OSErr                                    status;
  153.         unsigned char                 *p;
  154.         short         len;
  155.         unsigned char                    wildcard[] = "\p*";
  156.  
  157.  
  158.         if (!version)
  159.             version = wildcard;
  160.             
  161.         if (!revision)
  162.             revision = wildcard;
  163.             
  164.         if (!product)
  165.             product = wildcard;
  166.  
  167.         /******
  168.             Construct the combined product description string from the three components
  169.             size: length of each plus spaces between plus nil at end
  170.         ******/
  171.         status = PrNewPtr((Ptr*)productDescription, version[0] + 1 + revision[0] + 1 + product[0] + 1);
  172.         nrequire(status, failed_NewPtr);
  173.  
  174.         p = *productDescription;        
  175.         len = version[0];
  176.         memcpy(p, &(version[1]), len);                // copy the version string
  177.         p[len] = ' ';                                                    // add a space;
  178.         p += len + 1;
  179.         
  180.         len = revision[0];
  181.         memcpy(p, &(revision[1]), len);                // copy the revision string
  182.         p[len] = ' ';                                                    // add a space;
  183.         p += len + 1;
  184.         
  185.         len = product[0];
  186.         memcpy(p, &(product[1]), len);                // copy the revision string
  187.         p[len] = 0x00;                                                // add a null byte (pascal string)
  188.         
  189. failed_NewPtr:
  190.  
  191.         return(status);
  192.  
  193.     }//FHMakeProductDescription
  194.     
  195.     
  196. //<FF>
  197. /****************************************
  198.  
  199.     Function: FontHandlerInit:
  200.     
  201.     Function initializes the font handler and returns a context.
  202.     
  203.     context:                            (returned)         A font handler context.
  204.     docFontDbase:                    A valid docuemnt font database.
  205.     legalStreamTypes:            legal font types for streaming.
  206.     flags:                                Font Downloading flags.
  207.     version:                            pascal string for PostScript version number.
  208.     revision:                            pascal string for PostScript revision number.
  209.     product:                            pascal string for PostScript product name.
  210.     
  211. ****************************************/
  212. OSErr FontHandlerInit(TFontHandlerContext *context, CGXtoPostScriptDevice *psDevice, TFontDbase docFontDbase, scalerStreamTypeFlag legalStreamTypes, TFHDownloadFlags flags,
  213.                                                     unsigned char* version, unsigned char* revision, unsigned char* product)
  214.     {
  215.         OSErr                                    status;
  216.         TFontHandlerPtr                pFHContext;
  217.         Handle                                h;
  218.         long                                    i;
  219.         unsigned char                 *productDescription;
  220.         
  221.         /** Allocate the context **/
  222.         
  223.         status = PrNewHandleClear((Handle*)context, sizeof(TFontHandlerRec));
  224.         nrequire(status, failed_Alloc);
  225.  
  226.         /** Create the product descripton string **/
  227.         status = FHMakeProductDescription(&productDescription, version, revision, product);
  228.         nrequire(status, failed_product);
  229.  
  230.         /** Allocate the workspace handles **/
  231.         
  232.         for (i = 0; i < kMaxWrkSpaces; ++i) {
  233.         
  234.             nrequire(status = PrNewHandle(&h, 0), failed_WorkSpace);                // Allocate workspace handle.
  235.             pFHContext = *((TFontHandlerHdl)*context);
  236.             pFHContext->workHandle[i] = h;
  237.             pFHContext->workSize[i] = 0;
  238.  
  239. #if DEBUGLEVEL > 0
  240.             pFHContext->workHandleInUse[i] = false;
  241. #endif
  242.         
  243.         }//end for
  244.  
  245.         HLock((Handle) *context ); pFHContext = *((TFontHandlerHdl)*context);
  246.  
  247.         pFHContext->psDevice = psDevice;        
  248.         pFHContext->legalStreamTypes = legalStreamTypes;
  249.         pFHContext->asciiDownload = (flags & fhDownloadAscii) ? true : false;
  250.         pFHContext->useTypeZeroFonts = (flags & fhUseTypeZeroFonts) ? true : false;
  251.         pFHContext->productDescription = (char*)productDescription;
  252.         pFHContext->nextOffset = 0;
  253.         pFHContext->docDbase = docFontDbase;
  254.         pFHContext->numPrFonts = 0;
  255.         pFHContext->saveLevel = 0;
  256.         pFHContext->nextSnapShot = 1;                                // start snapshot id's at one.  zero means not found.
  257.         pFHContext->printerVM = 100000;                            // Just an initial value in case client doesn't set it.
  258.         pFHContext->vmAvailable = pFHContext->printerVM;
  259.         
  260.         pFHContext->documentStreamTypes = 0;
  261.         
  262.         status = FHCanPrinterHandleAllFonts(product, &(pFHContext->printerCanDoAllFonts) );
  263.         nrequire(status, failed_printerCan);
  264.  
  265.         pFHContext = *((TFontHandlerHdl)*context);
  266.         nrequire(status = RDInit(psDevice, &(pFHContext->rdMap)), failed_RD);
  267.         
  268.         /** Allocate the collections **/
  269.  
  270.         require_action(pFHContext->printerFontsOffsets = NewCollection(), failed_Collection, status = MemError(););        
  271.         require_action(pFHContext->snapShots = NewCollection(), failed_Collection1, status = MemError(););
  272.  
  273.         HUnlock((Handle) *context );
  274.         
  275.         /**********************
  276.             Now build the printer font database entries
  277.             based on the document font database.
  278.         ***********************/
  279.         
  280.         status = FHBuildPrinterFontList((TFontHandlerHdl)*context);
  281.         nrequire(status, failed_PrinterFonts);
  282.         
  283.         /******** 
  284.             Since building the printer font list did memory size querries for all downloaded fonts
  285.             and the the queries accumulate the returned stream types from the query,
  286.             the documentStreamTypes field in our context contains all font types necessary for
  287.             the document based on the document font database.  If the document did not require
  288.             true-type streaming (using patch) then disable the bit in the legal stream types field
  289.             that we use for streaming.
  290.         *********/
  291.         
  292.         pFHContext = *((TFontHandlerHdl)*context);  // in case it moved.
  293.         
  294.         if ( !(pFHContext->documentStreamTypes & truetypeStreamType) ) {
  295.         
  296.             pFHContext->legalStreamTypes &= ~truetypeStreamType;
  297.             
  298.             #if DEBUGLEVEL >= DEBUGFEEDBACK
  299.                 dprintf(trace, "Document did not need TT scaler, disabling trueTypeStreamType");
  300.             #endif
  301.             
  302.         }//end if
  303.         
  304.  
  305. failed_PrinterFonts:
  306.  
  307.         pFHContext = *((TFontHandlerHdl)*context);
  308.         
  309.         if (status != noErr) 
  310.             DisposeCollection(pFHContext->printerFontsOffsets);
  311.  
  312. failed_Collection1:        
  313. failed_Collection:
  314.  
  315.         if (status != noErr) {
  316.             OSErr saveStatus;
  317.             
  318.             pFHContext = *((TFontHandlerHdl)*context);
  319.             saveStatus = RDShutdown(pFHContext->rdMap);
  320.             ncheck(saveStatus);        
  321.         
  322.         }//end if
  323.  
  324. failed_RD:
  325.  
  326. failed_printerCan:
  327.             
  328. failed_WorkSpace:
  329.         /** If we failed after any workspaces were allocated, dispose of any that were allocated **/
  330.         
  331.         if (status != noErr) {
  332.         
  333.             for (i = 0; i < kMaxWrkSpaces; ++i) {
  334.             
  335.                 pFHContext = *((TFontHandlerHdl)*context);
  336.                 h = pFHContext->workHandle[i];
  337.                 if (h != nil)
  338.                     DisposeHandle(h);
  339.     
  340.             }//end for
  341.  
  342.             /* Dispose of the pointer allocated for the product description */
  343.             DisposePtr((Ptr)productDescription);
  344.             
  345.         }//end if
  346.         
  347.  
  348. failed_product:
  349.         if (status != noErr)
  350.             DisposeHandle((Handle)*context);
  351.  
  352. failed_Alloc:    
  353.  
  354.         ncheck(status);
  355.         
  356.         if (status != noErr)             // make sure we return nil if an error happened.
  357.             *context = nil;
  358.         
  359.         return(status);
  360.  
  361.     }//FontHandlerInit
  362.  
  363.  
  364. //<FF>
  365. /**********************************************
  366.  
  367.     Function:    FontHandlerShutdown
  368.     
  369.     Function disposes of a font handler context.
  370.     
  371.     context:            Font handler context to dispose of
  372.     
  373. ***********************************************/
  374. OSErr FontHandlerShutdown(TFontHandlerContext context)
  375.     {
  376.         OSErr                        status, saveStatus;
  377.         register                TFontHandlerPtr            pFHContext;    
  378.         long                        i;
  379.         Handle                    h;
  380.         long                        offset;
  381.         TPrinterFontRec    *printerFont;
  382.         
  383.         HLock((Handle)context);
  384.         pFHContext = *(TFontHandlerHdl)(context);
  385.  
  386.  
  387.         /* Dispose of any allocations haning off printer fonts */
  388.         
  389.         saveStatus = noErr; /* in case #items == 0 and loop won't execute */        
  390.         
  391.         for (i = 1; i <= CountCollectionItems(pFHContext->printerFontsOffsets); ++i) {
  392.         
  393.             saveStatus = GetIndexedCollectionItem(pFHContext->printerFontsOffsets, i, nil, &offset);
  394.             nrequire(saveStatus, failed_GetItem);
  395.             
  396.             printerFont = (TPrinterFontRec*)(pFHContext->printerFonts + offset);
  397.             
  398.             h = printerFont->glyphToCharCodeMap;
  399.  
  400.             if (h != nil)
  401.                 DisposeHandle(printerFont->glyphToCharCodeMap);
  402.                             
  403.         }//end for
  404.  
  405. failed_GetItem:        
  406.         /* Dispose of the collections */
  407.         
  408.         DisposeCollection(pFHContext->printerFontsOffsets);
  409.         DisposeCollection(pFHContext->snapShots);
  410.         
  411.         /* Dispose of the workspace handles */
  412.         
  413.         for (i = 0; i < kMaxWrkSpaces; ++i) {
  414.         
  415.             h = pFHContext->workHandle[i];
  416.             if (h != nil)
  417.                 DisposeHandle(h);
  418.  
  419.         }//end for
  420.  
  421.         /* Dispose of the product description string */
  422.     
  423.         DisposePtr(pFHContext->productDescription);
  424.         
  425.         /* dispose of the RDMap */
  426.         
  427.         status = RDShutdown(pFHContext->rdMap);
  428.         ncheck(status);
  429.  
  430.         /* Dispose of our context */
  431.         
  432.         DisposeHandle((Handle)context);
  433.         
  434.         if (saveStatus != noErr) 
  435.             status = saveStatus;
  436.             
  437.         return(status);
  438.         
  439.     }//FontHandlerShutdown
  440.     
  441.  
  442.  
  443.  
  444. /************************************
  445.  
  446.     Function: FontHandlerLockContext
  447.     
  448.     Routine to lock font handler data in memory.
  449.     
  450. *************************************/
  451. OSErr FontHandlerLockContext(TFontHandlerContext context)
  452.     {
  453.         HLock((Handle)context);
  454.         return(MemError());
  455.         
  456.     }//FontHandlerLockContext
  457.  
  458.  
  459.  
  460.  
  461. /************************************
  462.  
  463.     Function: FontHandlerUnlockContext
  464.     
  465.     Routine to unlock font handler data in memory.
  466.     
  467. *************************************/
  468. OSErr FontHandlerUnlockContext(TFontHandlerContext context)
  469.     {
  470.         HUnlock((Handle)context);
  471.         return(MemError());
  472.         
  473.     }//FontHandlerUnlockContext
  474.  
  475.  
  476. #if USECONTROLRESOURCES
  477.     /**********************************************
  478.         Routine FontHandlerGetProcSetList
  479.         Returns the range of id's and type of the resources for the
  480.         PostScript Procedure set, based upon the parameters specified at init time.
  481.  
  482.         context:        A valid imaging engine context.
  483.         needsHex:        Boolean indicating whether printer requires hex rather than binary.
  484.  
  485.     ************************************************/
  486.     OSErr    FontHandlerGetProcSetList(TFontHandlerContext context, gxProcSetListPtr procSetList, Boolean needsHex)
  487.         {
  488.             TFontHandlerPtr    pFHRec = *(TFontHandlerHdl)context;
  489.             Boolean                    needsScaler = false;
  490.             
  491.             if ( pFHRec->legalStreamTypes & truetypeStreamType)
  492.                 needsScaler = true;
  493.                     
  494.             procSetList->controlType = kControlResType;
  495.             procSetList->dataType = kBinaryResType;        
  496.             
  497.             if (!needsScaler)
  498.                 procSetList->controlid = kFHControlResID;
  499.             else
  500.                 if (needsHex)
  501.                     procSetList->controlid = kFHControlResID + 1;
  502.                 else
  503.                     procSetList->controlid = kFHControlResID + 2;
  504.             
  505.             return(noErr);
  506.         }//FontHandlerGetProcSetList
  507.  
  508. #else
  509.     
  510.     /***
  511.         This function directly downloads the font handler proceset.
  512.         Note:  In the library version we do not deal with the TrueType scaler.
  513.         Note, this version does not need a font handler context, just a device.
  514.     ****/
  515.     OSErr    FontHandlerDownloadProcSetList(CGXtoPostScriptDevice *theDevice)
  516.         {
  517.             OSErr        status = noErr;
  518.             Handle    hProc;
  519.  
  520.             status = FetchResource('wstr', kFHProcCopyRightNoticeID, &hProc);
  521.             nrequire(status, failed_fetchResource);
  522.             HLock(hProc);
  523.             short        size = *(short*)(*hProc);
  524.             char*        data = (*hProc) + sizeof(short);            // skip past size word in wstr resource.
  525.             status = theDevice->BufferData(data, size, gxNoBufferOptions);
  526.             ReleaseResource(hProc);
  527.  
  528.             if (status == noErr) {
  529.                 status = FetchResource('wstr', kFHStartProcId, &hProc);
  530.                 nrequire(status, failed_fetchResource1);
  531.                 HLock(hProc);
  532.                 size = *(short*)(*hProc);
  533.                 data = (*hProc) + sizeof(short);            // skip past size word in wstr resource.
  534.                 status = theDevice->BufferData(data, size, gxNoBufferOptions);
  535.                 ReleaseResource(hProc);
  536.             }//end if
  537.             
  538.             if (status == noErr) {
  539.                 status = FetchResource('wstr', kFHStartProcId + 1, &hProc);
  540.                 nrequire(status, failed_fetchResource2);
  541.                 HLock(hProc);
  542.                 size = *(short*)(*hProc);
  543.                 data = (*hProc) + sizeof(short);            // skip past size word in wstr resource.
  544.                 status = theDevice->BufferData(data, size, gxNoBufferOptions);
  545.                 ReleaseResource(hProc);
  546.             }//end if
  547.             
  548.     failed_fetchResource2:
  549.     failed_fetchResource1:
  550.     failed_fetchResource:
  551.             return(status);
  552.             
  553.         }//FontHandlerDownloadProcSetList
  554.  
  555. #endif
  556.  
  557. /*************************************************
  558.  
  559.     Routine: FontHandlerSetFontVM
  560.     
  561.     Routine called by client to let font handler know
  562.     how much VM is available for fonts.
  563.     
  564. **************************************************/
  565. OSErr FontHandlerSetFontVM(TFontHandlerContext context, long fontVM)
  566.     {
  567.         TFontHandlerPtr            pFHRec = *(TFontHandlerHdl)context;
  568.     
  569.         #if DEBUGLEVEL >= DEBUGFEEDBACK
  570.             dprintf(trace, "Font VM passed in: %d", fontVM);
  571.         #endif 
  572.         
  573.         pFHRec->printerVM = fontVM;
  574.         pFHRec->vmAvailable = fontVM;    
  575.             
  576.         return(noErr);
  577.         
  578.     }//FontHandlerSetFontVM
  579.  
  580.